package za.org.jcicada.genss.sensor.impl;

import java.util.Set;

import za.org.jcicada.comms.IConnection;
import za.org.jcicada.comms.impl.MessagingBase;
import za.org.jcicada.genss.ServiceURN;
import za.org.jcicada.genss.messages.Result;
import za.org.jcicada.genss.messages.TerminateServiceInform;
import za.org.jcicada.genss.sensor.ISensor;
import za.org.jcicada.genss.sensor.ISensorObserver;
import za.org.jcicada.genss.sensor.ISensorSubject;
import za.org.jcicada.genss.sensor.ISensorValue;
import za.org.jcicada.genss.sensor.SensorURN;
import za.org.jcicada.genss.sensor.messages.AttachReply;
import za.org.jcicada.genss.sensor.messages.DetachReply;
import za.org.jcicada.genss.sensor.messages.SensorSetReply;
import za.org.jcicada.genss.sensor.messages.SetSamplingStrategyReply;
import za.org.jcicada.genss.sensor.messages.UpdateSensorInform;
import za.org.jcicada.genss.sensor.messages.UpdateSensorStatusInform;
import za.org.jcicada.genss.sensor.messages.UpdateSensorTypeInform;

public class SensorMessaging extends MessagingBase {

    /**
     * Handle to sensor subject for invoking methods on.
     */
    ISensorSubject sensorSubject;

    /**
     * Handle to callback object for messages from the subject to the observer.
     */
    ISensorObserver sensorObserver;

    public SensorMessaging(IConnection connection, ISensorSubject sensorSubject) {
        super(connection);
        this.sensorSubject = sensorSubject;
        sensorObserver = new Responder();
    }

    public void onClose() throws Exception {
        sensorSubject.informDisconnect(sensorObserver);
    }

    public ISensorObserver getObserver() {
        return sensorObserver;
    }

    /**
     * Dispatch AttachRequest.
     */
    public void sensorAttachRequest(za.org.jcicada.genss.sensor.messages.AttachRequest msg) {
        sensorSubject.requestAttach(sensorObserver, msg.getSensorURNs());
    }

    /**
     * Dispatch DetachRequest.
     */
    public void sensorDetachRequest(za.org.jcicada.genss.sensor.messages.DetachRequest msg) {
        sensorSubject.requestDetach(sensorObserver, msg.getSensorURNs());
    }

    /**
     * Dispatch SensorSetRequest.
     */
    public void sensorSensorSetRequest(za.org.jcicada.genss.sensor.messages.SensorSetRequest msg) {
        sensorSubject.requestSensorSet(sensorObserver);
    }

    /**
     * Dispatch SetSamplingStrategyRequest.
     */
    public void sensorSetSamplingStrategyRequest(za.org.jcicada.genss.sensor.messages.SetSamplingStrategyRequest msg) {
        sensorSubject.requestSetSamplingStrategy(sensorObserver, msg.getSamplingStrategy());
    }

    /**
     * Implementation of ISensorObserver that sends messages back to a katcomms
     * connection.
     */
    public class Responder extends MessagingBase.ResponderBase implements ISensorObserver {

        /**
         * Called after attaching to a list of sensors using ISensorSubject.attach().
         */
        public void replyAttach(Result result, Set<SensorURN> sensorURNs) {
            sendMessage(new AttachReply(result, sensorURNs));
        }

        /**
         * Called after detaching from a list of sensors using ISensorSubject.detach().
         */
        public void replyDetach(Result result, Set<SensorURN> sensorURNs) {
            sendMessage(new DetachReply(result, sensorURNs));
        }
        
        /**
         * Called after detaching from a list of sensors using ISensorSubject.detach().
         */
        public void replySensorSet(Result result, int numSensors) {
            sendMessage(new SensorSetReply(result, numSensors));
        }
        
        /**
         * Called after setting a sensor sampling strategy
         */
        public void replySetSamplingStrategy(Result result) {
            sendMessage(new SetSamplingStrategyReply(result));
        }

        /**
         * Notify the observer of an update to the sensor.
         */
        public void informSensor(SensorURN sensorURN, ISensorValue value) {
            sendMessage(new UpdateSensorInform(sensorURN, value));
        }
        
        public void informSensorStatus(SensorURN sensorURN, SensorStatusValue statusValue) {
        	sendMessage(new UpdateSensorStatusInform(sensorURN, statusValue));
        }
        
        /**
         * Notify the observer of the sensor type.
         */
        public void informSensorType(SensorURN sensorURN, ISensor sensor) {
            sendMessage(new UpdateSensorTypeInform(sensorURN, sensor));
        }
        
        /**
         * Notify the observer that its attachment has been terminated.
         */
        public void informTerminateService(ServiceURN serviceURN) {
            sendMessage(new TerminateServiceInform(serviceURN));
        }

    }
}
